package com.butterknife.compiler;

import com.butterknife.annotation.BindView;
import com.butterknife.annotation.OnClick;
import com.google.auto.service.AutoService;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;

@AutoService(Processor.class)
public class ButterKnifeInvokeProcessor extends AbstractProcessor {


    // 1.支持的java版本
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }

    // 2 需要处理那些注解
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new HashSet<>();
        types.add(BindView.class.getCanonicalName());
        return types;
    }

    // 3需要生成文件，所以创建filer
    Filer filer;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        System.out.println("ZXH::ssssss");
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "ZXH::AAAAAA");
        filer = processingEnvironment.getFiler();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        //  获取aoo中所有的BindView的注解
        Set<? extends Element> bindViewElements = roundEnvironment.getElementsAnnotatedWith(BindView.class);

        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "ZXH::使用了BindView的注解有" + bindViewElements.size() + "个");
        Map<String, List<Element>> map = new HashMap<>();
        for (Element e : bindViewElements) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "注解》》》" + e.getSimpleName());
            VariableElement element = (VariableElement) e;
            String activityName = element.getEnclosingElement().getSimpleName().toString();
            List<? super VariableElement> list = map.computeIfAbsent(activityName, k -> new ArrayList<>());
            list.add(element);
        }

        Set<? extends Element> onClickElements = roundEnvironment.getElementsAnnotatedWith(OnClick.class);
        for (Element e : onClickElements) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "注解》》》" + e.getSimpleName());
            ExecutableElement element = (ExecutableElement) e;
            String activityName = element.getEnclosingElement().getSimpleName().toString();
            List<? super ExecutableElement> list = map.computeIfAbsent(activityName, k -> new ArrayList<>());
            list.add(element);
        }

        if (map.size() > 0) {
            Writer writer = null;
            Iterator<String> iterator = map.keySet().iterator();
            while (iterator.hasNext()) {
                String actName = iterator.next();
                List<? extends Element> elements = map.get(actName);
                // 随便找一个注解获取包名
                TypeElement enclosingElement = (TypeElement) elements.get(0).getEnclosingElement();
                String packageName = processingEnv.getElementUtils().getPackageOf(enclosingElement).toString();
                try {
                    JavaFileObject sourceFile = filer.createSourceFile(packageName + "." + actName + "_ViewBinding");
                    writer = sourceFile.openWriter();
                    writer.write("package " + packageName + ";\n");
                    writer.write("import " + packageName + ".IBinder;\n");
                    writer.write("public class " + actName + "_ViewBinding implements IBinder<" + packageName + "." + actName + "> {\n");
                    writer.write("    @Override\n");
                    writer.write("    public void bind(" + actName + " target) {\n");
                    for (Element e : elements) {
                        String variableName = e.getSimpleName().toString();
                        if (e instanceof VariableElement) {
                            int id = e.getAnnotation(BindView.class).value();
                            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "获取注解的值》" + id);
                            TypeMirror typeMirror = e.asType();
                            writer.write("        target." + variableName + " = (" + typeMirror + ")target.findViewById(" + id + ");\n");
                        }
                        if (e instanceof ExecutableElement) {
                            int id = e.getAnnotation(OnClick.class).value();
                            writer.write("        target.findViewById(" + id + ").setOnClickListener(v -> {\n            target." + variableName + "(v);\n        });\n");
                        }
                    }
                    writer.write("    }\n");
                    writer.write("}\n");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (writer != null) {
                        try {
                            writer.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }
        return true;
    }
}